#include "Dictionary.h"
#include <Windows.h>
#include <hash_map>

using namespace CoreLib::Basic;

template<typename TKey, typename TValue>
void PrintDictionary(const Dictionary<TKey, TValue> & dict)
{
	for (auto & pair : dict)
	{
		printf("%s -> %s\n", String(pair.Key).ToMultiByteString(), String(pair.Value).ToMultiByteString());
	}
}

void TestDictionary_1()
{
	Dictionary<int, int> intDict;
	for (int i = 0; i<30; i++)
	{
		intDict.Add(i, i*10);
	}
	for (int i = 0; i<30; i++)
	{
		if (i%4 == 0)
			intDict.Remove(i);
	}
	for (int i = 0; i<30; i++)
		if (i%8 == 0)
			intDict[i] = 800;
	printf("Contains 4: %d\n", intDict.ContainsKey(4));
	printf("Contains 8: %d\n", intDict.ContainsKey(8));
	int value = intDict[24];
	printf("value : %d\n", value);
	try
	{
		intDict.Add(18, -1);
	}
	catch (KeyExistsException)
	{
		printf("Insertion on 18, existed.\n");
	}
	try
	{
		int val = intDict[20];
	}
	catch (KeyNotFoundException)
	{
		printf("lookup on 20, not exists.\n");
	}
	PrintDictionary(intDict);
}
void TestDictionary_2()
{
	Dictionary<String, int> strDict;
	List<String> strs;
	for(int i = 0; i<50; i++)
	{
		String str = String(rand());
		strDict[str] = i;
		strs.Add(_Move(str));
	}
	bool failed = false;
	for (int i = 0; i<strs.Count(); i++)
		if (strDict[strs[i]] != i)
			failed = true;
	if (failed)
		printf("TestDictionary_2 failed\n");
	else
		printf("TestDictionary_2 success\n");
	PrintDictionary(strDict);
}
void TestDictionary_3()
{
	// hash_map
	LARGE_INTEGER counter, counter2, freq;
	QueryPerformanceFrequency(&freq);
	QueryPerformanceCounter(&counter);
	for (int q = 0; q<100; q++)
	{
		std::hash_map<int, int> map;
		for (int i = 0; i<100000; i++)
			map[i] = i*i;
		int rs = 0;
		for (int i = 0; i<100000; i++)
			rs += map[i];
	}
	QueryPerformanceCounter(&counter2);
	printf("hash_map: %fs\n", (counter2.QuadPart-counter.QuadPart)/(double)(freq.QuadPart));

	QueryPerformanceCounter(&counter);
	for (int q = 0; q<100; q++)
	{
		Dictionary<int, int> map;
		for (int i = 0; i<100000; i++)
			map[i] = i*i;
		int rs = 0;
		for (int i = 0; i<100000; i++)
			rs += map[i];
	}
	QueryPerformanceCounter(&counter2);
	printf("Dictionary: %fs\n", (counter2.QuadPart-counter.QuadPart)/(double)(freq.QuadPart));
}
void TestDictionary_4()
{
	Dictionary<int, int> map;
	for (int i = 0; i<100000; i++)
		map[i] = i*i;
	for (int i = 0; i<100000; i++)
		if (i%2 == 0)
			map.Remove(i);
	for (int i = 0; i<100000; i++)
		map[i] = i;
}
void TestDictionary_5()
{
	HashSet<String> strSet;
	for (int i = 1000; i<2000; i+=20)
		strSet.Add(String(i));
	bool failed = false;
	for (int i = 1000; i<2000; i++)
		if ((i%20 == 0) != (strSet.Contains(String(i))))
			failed = true;
	if (failed)
		printf("HashSet failed\n");
	else
		printf("HashSet success\n");
}


void TestDictionary()
{
	TestDictionary_1();
	TestDictionary_2();
	TestDictionary_3();
	TestDictionary_4();
	TestDictionary_5();

}